﻿using System;
using System.Collections.Generic;
using System.IO;
using AlgorytmyGenetyczne;
using AlgorytmyGenetyczne.Algorytmy;
using AlgorytmyGenetyczne.Historia;
using AlgorytmyGenetyczne.Kodowania;
using AlgorytmyGenetyczne.Operatory;
using AlgorytmyGenetyczne.WarunkiStopu;

namespace ProjektDoTestowaniaMariusz
{
    class Program
    {
        static void Main(string[] args)
        {
            //TestKodowaniaBinarnego();
            //TestKrzyzowaniaOsobnikow();
            //TestKrzyzowaniaOsobnikowZKodowaniem();
            //TestMutacji();
            //TestKodowaniaGraya();
            //TestObliczaniaWartosciFunkcji();
            for (int i = 0; i < 20; i++)
            {
                //TestKrzyzowaniaPopulacji();
            }
            //TestMutacji();
            //TestKodowaniaGraya();
            //TestCzyPAGWOgoleDziala();
            //TestFunkcjiDekodujacejDowolnaIloscZmiennych();

            System.Console.ReadKey();
        }

        static void TestCzyPAGWOgoleDziala()
        {
            AbstractKodowanie kodowanie = new KodowanieBinarne(10, -2, 2);
            List<AbstractKodowanie> kodowania = new List<AbstractKodowanie>();
            kodowania.Add(kodowanie);
            PAG algorytm = new PAG(kodowania);
            ((Krzyzowanie) algorytm.Krzyzowanie).IloscPunktowKrzyzowania = 3;
            algorytm.WielkoscPopulacji = 20;
            algorytm.Funkcja = new Funkcja("y = -pow(x1,2) - pow(x2,2)", 2);
            algorytm.PrawdopodobienstwoMutacji = 0.05;
            algorytm.WarunekStopu = new WarunekStopuIloscPokolen(100);
            System.Console.WriteLine(algorytm.ewolucja());
            //algorytm.Historia.zapiszDoPliku(@"E:\statsy1.txt");
        }

        static void zapiszDoPliku(string sciezka, string zawartosc)
        {
            StreamWriter streamWriter = new StreamWriter(sciezka);
            streamWriter.Write(zawartosc);
            streamWriter.Close();
        }

        //static void TestFunkcjiDekodujacejDowolnaIloscZmiennych()
        //{
        //    KodowanieBinarne kodowanie = new KodowanieBinarne(6, -2, 2);
        //    KodowanieBinarne kodowanie2 = new KodowanieBinarne(6, 0, 1);
        //    KodowanieBinarne kodowanie3 = new KodowanieBinarne(6, -1, 1);

        //    List<AbstractKodowanie> kodowania = new List<AbstractKodowanie>();
        //    kodowania.Add(kodowanie);
        //    kodowania.Add(kodowanie2);
        //    kodowania.Add(kodowanie3);

        //    double wartoscDoZakodowania = 1.637197;
        //    double wartoscDoZakodowania2 = 0.231977;
        //    double wartoscDoZakodowania3 = -0.995342;
        //    Genotyp genotyp = kodowanie.koduj(wartoscDoZakodowania) + kodowanie2.koduj(wartoscDoZakodowania2) + kodowanie3.koduj(wartoscDoZakodowania3);
        //    double[] wartoscZdekodowana = new PAG(kodowania).dekoduj(genotyp);


        //    System.Console.WriteLine(wartoscDoZakodowania);
        //    System.Console.WriteLine(wartoscDoZakodowania2);
        //    System.Console.WriteLine(wartoscDoZakodowania3);
        //    System.Console.WriteLine(genotyp);
        //    System.Console.WriteLine(wartoscZdekodowana[0]);
        //    System.Console.WriteLine(wartoscZdekodowana[1]);
        //    System.Console.WriteLine(wartoscZdekodowana[2]);
        //}

        static void TestKodowaniaBinarnego()
        {
            System.Console.WriteLine("TestKodowanaBinarnego");
            KodowanieBinarne kodowanie = new KodowanieBinarne(6, 0, 1);
            double wartoscDoZakodowania = 0.637197;
            double wartoscDoZakodowania2 = 0.231977;
            Genotyp genotyp = kodowanie.koduj(wartoscDoZakodowania) + kodowanie.koduj(wartoscDoZakodowania2);
            double wartoscZdekodowana = (double)kodowanie.dekoduj(genotyp.fragmentGenotypu(0, kodowanie.IloscBitow - 1));
            double wartoscZdekodowana2 =
                (double)kodowanie.dekoduj(genotyp.fragmentGenotypu(kodowanie.IloscBitow, genotyp.Length - 1));

            System.Console.WriteLine(wartoscDoZakodowania);
            System.Console.WriteLine(wartoscDoZakodowania2);
            System.Console.WriteLine(genotyp);
            System.Console.WriteLine(wartoscZdekodowana);
            System.Console.WriteLine(wartoscZdekodowana2);

            kodowanie = new KodowanieBinarne(6, 0, 1);
            wartoscDoZakodowania = 0.637197;
            genotyp = kodowanie.koduj(wartoscDoZakodowania);
            genotyp[17] = !genotyp[17];
            wartoscZdekodowana = (double)kodowanie.dekoduj(genotyp);

            System.Console.WriteLine(wartoscDoZakodowania);
            System.Console.WriteLine(genotyp);
            System.Console.WriteLine(wartoscZdekodowana);

            kodowanie = new KodowanieBinarne(1, 4, 8);
            wartoscDoZakodowania = 7;
            genotyp = kodowanie.koduj(wartoscDoZakodowania);
            wartoscZdekodowana = (double)kodowanie.dekoduj(genotyp);

            System.Console.WriteLine(wartoscDoZakodowania);
            System.Console.WriteLine(genotyp);
            System.Console.WriteLine(wartoscZdekodowana);
        }

        static void TestKodowaniaGraya()
        {
            System.Console.WriteLine("TestKodowanaGraya");
            KodowanieGraya kodowanie = new KodowanieGraya(6, -1, 2);
            double wartoscDoZakodowania = 0.637197;
            double wartoscDoZakodowania2 = 1.0;
            Genotyp genotyp = kodowanie.koduj(wartoscDoZakodowania) + kodowanie.koduj(wartoscDoZakodowania2);
            double wartoscZdekodowana = (double)kodowanie.dekoduj(genotyp.fragmentGenotypu(0, kodowanie.IloscBitow - 1));
            double wartoscZdekodowana2 =
                (double)kodowanie.dekoduj(genotyp.fragmentGenotypu(kodowanie.IloscBitow, genotyp.Length - 1));

            System.Console.WriteLine(wartoscDoZakodowania);
            System.Console.WriteLine(wartoscDoZakodowania2);
            System.Console.WriteLine(genotyp);
            System.Console.WriteLine(wartoscZdekodowana);
            System.Console.WriteLine(wartoscZdekodowana2);
            System.Console.WriteLine();

            kodowanie = new KodowanieGraya(6, 0, 1);
            wartoscDoZakodowania = 0.637197;
            genotyp = kodowanie.koduj(wartoscDoZakodowania);
            genotyp[17] = !genotyp[17];
            wartoscZdekodowana = (double)kodowanie.dekoduj(genotyp);

            System.Console.WriteLine(wartoscDoZakodowania);
            System.Console.WriteLine(genotyp);
            System.Console.WriteLine(wartoscZdekodowana);

            System.Console.WriteLine(wartoscDoZakodowania);
            System.Console.WriteLine(genotyp);
            System.Console.WriteLine(wartoscZdekodowana);

            kodowanie = new KodowanieGraya(1, 4, 8);
            wartoscDoZakodowania = 7;
            genotyp = kodowanie.koduj(wartoscDoZakodowania);
            wartoscZdekodowana = (double)kodowanie.dekoduj(genotyp);

            System.Console.WriteLine(wartoscDoZakodowania);
            System.Console.WriteLine(genotyp);
            System.Console.WriteLine(wartoscZdekodowana);
        }

        static void TestKrzyzowaniaOsobnikow()
        {
            System.Console.WriteLine("\n\n-----------------------------\nTEST-KRZYZOWANIE-OSOBNIKOW-BEZ-KODOWANIA");
            Krzyzowanie krzyzowanie = new Krzyzowanie(0.25, 1);
            Osobnik rodzic1 = new Osobnik();
            Osobnik rodzic2 = new Osobnik();

            bool[] geny1 = { true, false, false, true, true, true, false, false, true, false, true, false };
            rodzic1.Genotyp.Geny = geny1;
            System.Console.WriteLine("Rodzic1   = " + rodzic1.Genotyp.wyswietlNieodwrocony());

            bool[] geny2 = { true, true, false, false, false, false, true, true, true, true, false, false };
            rodzic2.Genotyp.Geny = geny2;
            System.Console.WriteLine("Rodzic2   = " + rodzic2.Genotyp.wyswietlNieodwrocony());

            Osobnik[] dzieci = krzyzowanie.krzyzujOsobnikow(rodzic1, rodzic2);
            for (int i = 0; i < dzieci.Length; i++)
            {
                System.Console.WriteLine("Dziecko" + i + 1 + " = " + dzieci[i].Genotyp.wyswietlNieodwrocony());
            }

        }

        static void TestKrzyzowaniaPopulacji()
        {
            System.Console.WriteLine("\n\n-----------------------------\nTEST-KRZYZOWANIA-POPULACJI");
            AbstractKodowanie kodowanie = new KodowanieGraya(6, 0, 1);
            int ILOSC_OSOBNIKOW = 10;
            int DLUGOSC_GENOTYPU = 10;
            Random random = new Random();
            Krzyzowanie krzyzowanie = new Krzyzowanie(0.25, 1);
            Populacja populacja = new Populacja();

            //GENEROWANIE POPULACJI
            bool[] geny = new bool[DLUGOSC_GENOTYPU];
            for (int i = 0; i < ILOSC_OSOBNIKOW; i++)
            {
                Osobnik rodzic = new Osobnik();
                rodzic.Genotyp = kodowanie.koduj(random.NextDouble());
                System.Console.WriteLine("Rodzic " + (i + 1) + " = " + rodzic.Genotyp);
                populacja.Osobnicy.Add(rodzic);
            }
            System.Console.WriteLine("\nPOPULACJA POCZATKOWA");
            foreach (Osobnik osobnik in populacja.Osobnicy)
            {
                System.Console.WriteLine(kodowanie.dekoduj(osobnik.Genotyp));
            }
            System.Console.WriteLine("\nROZPOCZYNAM KRZYZOWANIE");
            krzyzowanie.wykonaj(populacja);
            System.Console.WriteLine("ZAKONCZONO KRZYZOWANIE\n");

            for (int i = 0; i < populacja.Osobnicy.Count; i++)
            {
                System.Console.WriteLine("Osobnik " + (i + 1) + " = " + populacja.Osobnicy[i].Genotyp);
            }

            System.Console.WriteLine("\nPOPULACJA KONCOWA");
            foreach (Osobnik osobnik in populacja.Osobnicy)
            {
                System.Console.WriteLine(kodowanie.dekoduj(osobnik.Genotyp));
            }
        }

        static void TestKrzyzowaniaOsobnikowZKodowaniem()
        {
            System.Console.WriteLine("\n\n-----------------------------\nTEST-KRZYZOWANIE-OSOBNIKOW-Z-KODOWANIEM");
            KodowanieBinarne kodowanie = new KodowanieBinarne(6, -1, 2);
            Krzyzowanie krzyzowanie = new Krzyzowanie(0.25, 1);
            Random random = new Random();
            krzyzowanie.IloscPunktowKrzyzowania = 5;

            double wartosc1 = random.NextDouble();
            double wartosc2 = random.NextDouble();
            Genotyp genotyp1 = kodowanie.koduj(wartosc1);
            Genotyp genotyp2 = kodowanie.koduj(wartosc2);
            Osobnik rodzic1 = new Osobnik();
            Osobnik rodzic2 = new Osobnik();
            rodzic1.Genotyp = genotyp1;
            rodzic2.Genotyp = genotyp2;
            System.Console.WriteLine("Rodzic1 = " + wartosc1 + "\n" + genotyp1);
            System.Console.WriteLine("\n\nRodzic2 = " + wartosc2 + "\n" + genotyp2);
            Osobnik[] dzieci = krzyzowanie.krzyzujOsobnikow(rodzic1, rodzic2);
            for (int i = 0; i < dzieci.Length; i++)
            {
                System.Console.WriteLine("\n\nDziecko" + (i + 1) + " = " + (double)kodowanie.dekoduj(dzieci[i].Genotyp) + "\n" + dzieci[i].Genotyp);

            }
        }

        static void TestMutacji()
        {
            System.Console.WriteLine("\n\n-----------------------------\nTEST-MUTACJI");
            Mutacja mutacja = new Mutacja(0.01);
            Populacja populacja = new Populacja();
            Osobnik rodzic1 = new Osobnik();
            bool[] geny1 = { true, true, true, true, true, true, true, true, true, true, true, true };
            rodzic1.Genotyp.Geny = geny1;
            System.Console.WriteLine("Rodzic1 = " + rodzic1.Genotyp.wyswietlNieodwrocony());
            populacja.Osobnicy.Add(rodzic1);
            mutacja.wykonaj(populacja);
            System.Console.WriteLine("Rodzic1 = " + rodzic1.Genotyp.wyswietlNieodwrocony());
        }

        static void TestObliczaniaWartosciFunkcji()
        {
            System.Console.WriteLine("\n\n-----------------------------\nTEST-OBLICZANIA-WARTOSCI-FUNKCJI");
            IFunkcja funkcja = new Funkcja("y = pow(x1,2) + pow(x2,2)", 2);
            System.Console.WriteLine("Wzor funkcji :: " + funkcja);
            double x1 = 2.0;
            double x2 = 3.0;
            double[] argumenty = { x1, x2 };
            System.Console.WriteLine("TEST FUNKCJI :: dla argumentow x1 = " + x1 + "  ,  x2 = " + x2);
            System.Console.WriteLine("TEST FUNKCJI :: wynik = " + funkcja.wartosc(argumenty));
        }
    }
}
